package com.bzsg.rightsManagementSystem.config.security_config

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.config.annotation.ObjectPostProcessor
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter


@Configuration
@EnableWebSecurity
class WebSecurityConfig {
    //登录成功处理逻辑
    @Autowired
    private lateinit var authenticationSuccessHandler: CustomizeAuthenticationSuccessHandler

    //登录失败处理逻辑
    @Autowired
    private lateinit var authenticationFailureHandler: CustomizeAuthenticationFailureHandler

    //权限拒绝处理逻辑
    @Autowired
    private lateinit var accessDeniedHandler: CustomizeAccessDeniedHandler

    //匿名用户访问无权限资源时的异常
    @Autowired
    private lateinit var authenticationEntryPoint: CustomizeAuthenticationEntryPoint

    //登出成功处理逻辑
    @Autowired
    private lateinit var logoutSuccessHandler: CustomizeLogoutSuccessHandler

    //访问决策管理器
    @Autowired
    private lateinit var accessDecisionManager: CustomizeAccessDecisionManager

    //实现权限拦截
    @Autowired
    private lateinit var securityMetadataSource: CustomizeFilterInvocationSecurityMetadataSource

    @Autowired
    private lateinit var securityInterceptor: CustomizeAbstractSecurityInterceptor

    @Autowired   //自动获取到bean容器里面的对象
    private lateinit var authenticationConfiguration: AuthenticationConfiguration

    
    @Bean
    fun passwordEncoder(): BCryptPasswordEncoder {
        // 设置默认的加密方式（强hash方式加密）
        return BCryptPasswordEncoder()
    }

    @Bean
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        http.authorizeRequests()
            .antMatchers("/login").permitAll() //全部都可以访问
            .anyRequest().authenticated() //其它接口 任意用户认证后可以访问


        http.cors().and().csrf().disable()
        http.authorizeRequests().withObjectPostProcessor(object : ObjectPostProcessor<FilterSecurityInterceptor> {
            override fun <O : FilterSecurityInterceptor> postProcess(o: O): O {
                o.accessDecisionManager = accessDecisionManager //决策管理器
                o.securityMetadataSource = securityMetadataSource //安全元数据源
                return o
            }
        })
            .and().logout().permitAll().logoutSuccessHandler(logoutSuccessHandler) //允许所有用户//登出成功处理逻辑
            .and().formLogin().permitAll().successHandler(authenticationSuccessHandler). //登录成功处理逻辑
            failureHandler(authenticationFailureHandler)//登录失败处理逻辑
            .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler)//异常处理(权限拒绝、登录失效等)
            .accessDeniedHandler(accessDeniedHandler)//权限拒绝处理逻辑
            .authenticationEntryPoint(authenticationEntryPoint)//匿名用户访问无权限资源时的异常处理
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

        http.addFilterBefore(jwtFilterBean(), UsernamePasswordAuthenticationFilter::class.java)
        http.addFilterAt(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter::class.java)
        http.addFilterBefore(securityInterceptor, FilterSecurityInterceptor::class.java)
        return http.build()

    }

    @Bean
    fun webSecurityCustomizer(): WebSecurityCustomizer = WebSecurityCustomizer {}


    @Bean
    fun jwtFilterBean(): JwtFilter {
        return JwtFilter()
    }


    @Bean
    @Throws(Exception::class)
    fun customAuthenticationFilter(): CustomAuthenticationFilter {
        val filter = CustomAuthenticationFilter()
        filter.setAuthenticationSuccessHandler(authenticationSuccessHandler)
        filter.setAuthenticationFailureHandler(authenticationFailureHandler)
        filter.setFilterProcessesUrl("/login")
        filter.setAuthenticationManager(authenticationManager(authenticationConfiguration))
        return filter
    }


    @Bean
    fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager {
        return authenticationConfiguration.authenticationManager
    }


}